#include "transFile.h"

int recv_code(int sockFd, int *pcode, long total){
    ssize_t ret = recvn(sockFd, pcode, sizeof(pcode));
    ERROR_CHECK(ret, -1, "recvn");
    printf("train->code = %d\n", *pcode);
    return 0;
}

int recv_once(int sockFd, train_t *ptrain, long total){
    ssize_t ret = recvn(sockFd, &ptrain->length, sizeof(ptrain->length));
    ERROR_CHECK(ret, -1, "recvn");
    //printf("train->length = %d\n", ptrain->length);

    ret = recvn(sockFd, &ptrain->data, sizeof(ptrain->data));
    ERROR_CHECK(ret, -1, "recvn");
    //printf("train->data = %s\n", ptrain->data);

    ret = recvn(sockFd, &ptrain->code, sizeof(ptrain->code));
    ERROR_CHECK(ret, -1, "recvn");
    //printf("train->code = %d\n", ptrain->code);

    return 0;
}

int recvn(int sockFd, void *buf, long total){
    //netFd - sockFd, buf - 缓冲区首地址, total - 接收文件总大小
    char *p = (char *)buf;
    long curSize = 0;
    while(curSize < total){
        ssize_t ret = recv(sockFd, p+curSize, total-curSize, 0);
        ERROR_CHECK(ret, -1, "recv");
        if(0 == ret){
            return 1;
        }
        curSize += ret;
    }
    return 0;
}

int recvFile(int sockFd, train_t *ptrain){
    train_t train;
    //1、接收文件名
    char filename[4096] = {0};
    recvn(sockFd, &train.length, sizeof(train.length));//文件名的长度
    recvn(sockFd, &train.data, train.length);//文件名
    memcpy(filename, train.data, train.length);
    printf("recv filename = %s\n", filename);

    //2、接收文件大小
    off_t fileSize;
    recvn(sockFd, &train.length, sizeof(train.length));
    recvn(sockFd, &train.data, train.length);
    memcpy(&fileSize, train.data, train.length);
    printf("recv fileSize = %ld\n", fileSize);

    //3、接收文件
    int fd = open(filename, O_CREAT|O_RDWR|O_TRUNC, 0666);
    ftruncate(fd, fileSize);
    char *p = (char *)mmap(NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    ERROR_CHECK(p, MAP_FAILED, "mmap");
    recvn(sockFd, p, fileSize);
    munmap(p, fileSize);
    printf("recvFile done!\n");
    close(fd);

    return 0;
}

int transFile(int netFd){
    train_t train;
    //1、先发送文件名
    char filename[] = "file1";
    train.length = strlen(filename);
    memcpy(train.data, filename, train.length);
    send(netFd, &train, sizeof(train.length)+train.length, MSG_NOSIGNAL);
    
    //2、发送文件大小
    struct stat statbuf;
    int fd = open(filename, O_RDWR);
    fstat(fd, &statbuf);
    train.length = sizeof(off_t);
    memcpy(train.data, &statbuf.st_size, train.length);
    send(netFd, &train, sizeof(train.length)+train.length, MSG_NOSIGNAL);

    //3、发送文件
    sleep(2);
    sendfile(netFd, fd, NULL, statbuf.st_size);
    printf("transFile done!\n");
    close(fd);

    return 0;
}

void remove_newline(char *str) {
    size_t len = strcspn(str, "\n");
    if (str[len] == '\n') {
        str[len] = '\0';
    }
}

int parseStr(char beforeParseStr[], char* afterParseStr[], const char p[], int *argcNum, train_t *ptrain){
    *argcNum = 0;
    char* token = NULL;
    token = strtok(beforeParseStr, p);

    if(token == NULL){
        printf("parseStr输入指令错误, 请重新输入!\n");
        return -1;
    }

    remove_newline(token);
    //printf("token = %s\n", token);
    afterParseStr[*argcNum] = token;

    if(strcmp(p, " ") == 0){
        if (strcmp(token, "ls") == 0) {
            ptrain->code = LS_APPLY;
        } 
        else if (strcmp(token, "cd") == 0) {
            ptrain->code = CD_APPLY;
        } 
        else if (strcmp(token, "pwd") == 0) {
            ptrain->code = PWD_APPLY;
        } 
        else if (strcmp(token, "puts") == 0) {
            ptrain->code = PUTS_APPLY;
        } 
        else if (strcmp(token, "gets") == 0) {
            ptrain->code = GETS_APPLY;
        } 
        else if (strcmp(token, "rm") == 0) {
            ptrain->code = RM_APPLY;
        } 
        else if (strcmp(token, "mkdir") == 0) {
            ptrain->code = MKDIR_APPLY;
        } 
        else if (strcmp(token, "rmdir") == 0) {
            ptrain->code = RMDIR_APPLY;
        } 
        else {
            printf("输入指令错误, 请重新输入!\n");
            return -1;
        }
    }
    
    ++(*argcNum);
    token = strtok(NULL, p);
    while (token != NULL) {
        remove_newline(token);
        afterParseStr[*argcNum] = token;
        ++(*argcNum);
        token = strtok(NULL, p);
    }

    return 0;
}